package org.movee.net.cfg.parser.parser.juniper;

import org.movee.net.cfg.parser.domain.model.AddressFamilyType;
import org.movee.net.cfg.parser.domain.model.ConfigModel;
import org.movee.net.cfg.parser.utils.OrikaSupplier;
import ma.glasnost.orika.MapperFacade;
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

import java.util.Map;
import java.util.TreeMap;

/**
 *
 *
 * @author 
 */
public class JuniperConfigModelConverter implements Converter<JuniperConfigModel, ConfigModel> {

    private final MapperFacade orika = OrikaSupplier.ORIKA;

    @Nullable
    @Override
    public ConfigModel convert(@NonNull JuniperConfigModel source) {

        ConfigModel.Netware netware = createNetware(source.getNetware());

        Map<String, ConfigModel.IpUnit> ipUnits = new TreeMap<>();
        Map<String, ConfigModel.InterfaceUnit> intfUnits = new TreeMap<>();
        for (JuniperConfigModel.Interface intf : source.getIntfs().values()) {

            ConfigModel.Interface dstIntf = orika.map(intf, ConfigModel.Interface.class);

            ConfigModel.InterfaceUnit intfUnit = new ConfigModel.InterfaceUnit();
            intfUnit.setIntf(dstIntf);
            if (StringUtils.hasLength(intf.getAd8023())) {
                intfUnit.setPIntf(intf.getAd8023());
            }

            for (JuniperConfigModel.InterfaceIp ip : intf.getIps()) {
                ConfigModel.Ip dstIp = orika.map(ip, ConfigModel.Ip.class);
                dstIp.setFamily(AddressFamilyType.IPV4.name());

                ConfigModel.IpUnit ipUnit = new ConfigModel.IpUnit();
                ipUnit.setIp(dstIp);
                ipUnit.setIntf(dstIntf.getName());

                ipUnits.put(dstIp.getIpAddress(), ipUnit);

                intfUnit.getIpv4s().add(dstIp.getIpAddress());
            }

            for (JuniperConfigModel.InterfaceIp6 ip : intf.getIp6s()) {
                ConfigModel.Ip dstIp = orika.map(ip, ConfigModel.Ip.class);
                dstIp.setFamily(AddressFamilyType.IPV6.name());

                ConfigModel.IpUnit ipUnit = new ConfigModel.IpUnit();
                ipUnit.setIp(dstIp);
                ipUnit.setIntf(dstIntf.getName());

                ipUnits.put(dstIp.getIpAddress(), ipUnit);

                intfUnit.getIpv6s().add(dstIp.getIpAddress());
            }

            intfUnits.put(dstIntf.getName(), intfUnit);
        }

        for (ConfigModel.InterfaceUnit intfUnit : intfUnits.values()) {
            if (StringUtils.hasLength(intfUnit.getPIntf())) {
                ConfigModel.InterfaceUnit parent = intfUnits.get(intfUnit.getPIntf());
                if (parent != null) {
                    parent.getCIntfs().add(intfUnit.getIntf().getName());
                }
            }
        }

        return new ConfigModel()
                .setMgmtIp(source.getMgmtIp())
                .setTimestamp(source.getTimestamp())
                .setNetware(netware)
                .setInterfaces(intfUnits)
                .setIps(ipUnits)
                .setBgp(null);
    }

    private ConfigModel.Netware createNetware(JuniperConfigModel.Netware netware) {
        return orika.map(netware, ConfigModel.Netware.class);
    }

}
